//客户端
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sqlite3.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
#define N 16
typedef struct sockaddr SA;
 
enum CMD
{
    R = 1, //注册
    L,     //登录
    Q,     //查询
    H      //历史
};
 
typedef struct
{
    int type;
    char name[N];
    char data[256]; // password or word
} MSG;
 
/**
 * @brief 客户端注册
 * 用户输入用户名和密码
 * 封装消息
 * 发送
 * 接收并输出结果
 */
void do_register(int sockfd, MSG *pbuf)
{
    pbuf->type = R; 
    printf("请输入用户名\n");
    scanf("%2s", pbuf->name);
    printf("请输入密码：\n");
    scanf("%s", pbuf->data);
     // 发送注册消息
    if (send(sockfd, pbuf, sizeof(MSG), 0) == -1) {
        perror("send failed");
        return;
    }
    // 接收服务器的响应
    if (recv(sockfd, pbuf, sizeof(MSG), 0) == -1) {
        perror("recv failed");
        return;
    }
    printf("注册：%s\n\n", pbuf->data);
}
 
/**
 * @brief 客户端登录
 * 用户输入用户名和密码
 * 封装消息
 * 发送
 * 接收并输出结果
 * @return 成功返回1 失败返回0
 */
int do_login(int sockfd, MSG *pbuf)
{
    pbuf->type = L;
    printf("请输入用户名：");
    scanf("%s", pbuf->name);
    printf("请输入密码:");
     scanf("%s", pbuf->data);
    // 发送登录消息
    if (send(sockfd, pbuf, sizeof(MSG), 0) == -1) {
        perror("send failed");
        return 0;
    }
    // 接收服务器的响应
    if (recv(sockfd, pbuf, sizeof(MSG), 0) == -1) {
        perror("recv failed");
        return 0;
    }
    if (strncmp(pbuf->data, "OK", 3) == 0)
    {
        printf("login success\n\n");
        return 1;
    }
    else
    {
        printf("登录：%s\n\n", pbuf->data);
        return 0;
    }
}
 
/**
 * @brief 客户端查询
 * 查询历史
 */
void do_history(int sockfd, MSG *pbuf)
{
    pbuf->type = H;
    if (send(sockfd, pbuf, sizeof(MSG), 0) == -1) {
        perror("send failed");
        return;
    }
    while (1) {
        if (recv(sockfd, pbuf, sizeof(MSG), 0) == -1) {
            perror("recv failed");
            break;
        }
        if (pbuf->data[0] == '\0')
            break;
    
        printf("%s\n", pbuf->data);
        
    }
}
 
/**
 * @brief 客户端查询
 * 输入单词或“#”
 * 封装消息
 * 发送
 * 接收并输出结果
 */
void do_query(int sockfd, MSG *pbuf)
{
    pbuf->type = Q;
    while (1)
    {
        printf("需要查询的单词：");
        scanf("%s", pbuf->data);
        if (strcmp(pbuf->data, "#") == 0)
            break;
        send(sockfd, pbuf, sizeof(MSG), 0);
        recv(sockfd, pbuf, sizeof(MSG), 0);
        printf("结果：%s\n", pbuf->data);
        printf("\n");
    }
}
 
void enter_query(int sockfd, MSG *buf)
{
    int input;
    char cleanbuf[64];
 
    while (1)
    {
        printf("***********************************************\n");
        printf("* 1: query_word   2: history_record   3: quit *\n");
        printf("***********************************************\n");
        printf("please choose : ");
        //获取用户输入
        if (scanf("%d", &input) == 0)
        {
            fgets(cleanbuf, 64, stdin); //类型错误需要重新清除输入缓冲区
            continue;
        }
 
        switch (input)
        {
        case 1:
            printf("\n");
            do_query(sockfd, buf);
            printf("\n");
            break;
        case 2:
            printf("\n");
            do_history(sockfd, buf);
            printf("\n");
            break;
        case 3:
            return;
        default:
            break;
        }
    }
}
 
int main(int argc, char *argv[])
{
    int sockfd, login = 0;
    struct sockaddr_in servaddr;
    MSG buf;
    char clean[64];
 
    if (argc < 3)
    {
        printf("Usage : %s <serv_ip> <serv_port>\n", argv[0]);
        exit(-1);
    }
 
    //创建客户端socket
    if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("fail to socket");
        exit(-1);
    }
 
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = PF_INET;
    servaddr.sin_port = htons(atoi(argv[2]));
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);
 
    //连接服务器
    if (connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) < 0)
    {
        perror("fail to connect");
        exit(-1);
    }
 
    int input;
    char cleanbuf[64];
    while (1)
    {
        printf("************************************\n");
        printf("* 1: register   2: login   3: quit *\n");
        printf("************************************\n");
        printf("please choose : ");
        //获取用户输入
        if (scanf("%d", &input) == 0)
        {
            fgets(cleanbuf, 64, stdin); //类型错误需要重新清除输入缓冲区
            continue;
        }
 
        switch (input)
        {
        case 1:
            do_register(sockfd, &buf);
            break;
        case 2:
            if (do_login(sockfd, &buf) == 1)
            { //成功
                enter_query(sockfd, &buf);
            }
            break;
        case 3:
            close(sockfd);
            exit(0);
            break;
        default:
            break;
        }
    }
}